home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Utilities
/
Magnify
/
Source
/
MagnifyView.m
< prev
next >
Wrap
Text File
|
1992-11-09
|
8KB
|
319 lines
/* File: MagnifyView.m - View class for 'Magnify'
*
* By: Christopher Lane
* Symbolic Systems Resources Group
* Knowledge Systems Laboratory
* Stanford University
*
* Date: 9 November 1992
*
* Copyright: 1990, 1991 & 1992 by The Leland Stanford Junior University.
* This program may be distributed without restriction for non-commercial use.
*/
#import "Magnify.h"
#import "MagnifyView.h"
#import "NXCursorPatch.h"
#import "DefaultsTable.h"
#import <appkit/Pasteboard.h>
#define GRIDLINEMODE NX_COPY
#define GRIDLINEWIDTH ((float) 1.0)
#define NX_CMYKMASK (NX_MONOTONICMASK | NX_COLORMASK)
#define NX_EMPTYMASK (NX_COMMANDMASK & (~ NX_COMMANDMASK))
#define MAGNIFYLEVEL (100)
#define NXSetWindowLevel _NXSetWindowLevel
extern int NXSetWindowLevel(int, int);
@implementation MagnifyView
- initFrame:(const NXRect *) frameRect;
{
[super initFrame:frameRect];
frozen = NO;
lock = mutex_alloc();
flags = NX_EMPTYMASK;
mouse = frameRect->origin;
scale = getFloatDefault("Scale");
showGrid = getBoolDefault("ShowGrid");
gridSize = getFloatDefault("GridSize");
showCursor = getBoolDefault("ShowCursor");
return [self createWindows];
}
- (BOOL) acceptsFirstResponder { return YES; }
- copy:sender
{
char *buffer;
NXStream *stream;
int length, maxLength;
Pasteboard *pasteboard = [Pasteboard new];
[pasteboard declareTypes:&NXPostScriptPboardType num:1 owner:self];
stream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
[self copyPSCodeInside:&bounds to:stream];
NXFlush(stream);
NXGetMemoryBuffer(stream, &buffer, &length, &maxLength);
[pasteboard writeType:NXPostScriptPboard data:buffer length:length];
NXCloseMemory(stream, NX_FREEBUFFER);
return self;
}
- drawSelf:(const NXRect *) rects :(int) rectCount
{
mutex_lock(lock); {
NXDrawBitmap(&virtualBounds, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel, bitsPerPixel, bytesPerRow,
(BOOL) (planarConfig == NX_PLANAR),
(BOOL) ((photoInt & NX_ALPHAMASK) == NX_ALPHAMASK),
colorSpace, data);
if(showGrid) [self drawGrid];
if(showCursor) [self drawCursor];
} mutex_unlock(lock);
return self;
}
- free
{
unsigned int i;
if (invisibleWindow != nil) [invisibleWindow close];
for(i = 0; i < NX_MAXPLANES; i++) if (data[i] != NULL) free(data[i]);
return [super free];
}
- sizeTo:(NXCoord) newWidth :(NXCoord) newHeight;
{
id result;
mutex_lock(lock); {
result = [super sizeTo:newWidth :newHeight];
} mutex_unlock(lock);
[self createWindows];
return result;
}
- mouseMoved:(NXEvent *)theEvent
{
int eventMask;
if (mutex_try_lock(lock)) {
eventMask = [window removeFromEventMask:NX_MOUSEMOVEDMASK]; {
while([NXApp peekAndGetNextEvent:NX_MOUSEMOVEDMASK] != NULL);
mouse = theEvent->location;
[window convertBaseToScreen:&mouse];
} [window setEventMask:eventMask];
mutex_unlock(lock);
[[self updateBitmap:&mouse] display];
}
return [nextResponder mouseMoved:theEvent];
}
- flagsChanged:(NXEvent *)theEvent
{
flags = theEvent->flags;
return [nextResponder flagsChanged:theEvent];
}
- drawCursor
{
NXSize size;
NXPoint point;
NXImage *image;
NXCursor *cursor;
const NXPoint *hotSpot;
if((cursor = [NXCursor currentCursor]) == nil) return nil;
[(image = [cursor image]) getSize:&size];
hotSpot = [cursor hotSpot];
point.x = rint((bounds.size.width + scale) * HALF) - hotSpot->x;
point.y = rint((bounds.size.height + scale) * HALF) - (size.height + hotSpot->y);
[image composite:NX_SOVER toPoint:&point];
return self;
}
- drawGrid
{
float x, y, max;
max = bounds.origin.y + bounds.size.height;
for(y = bounds.origin.y; y < max; y += gridSize)
PScompositerect(bounds.origin.x, y, bounds.size.width, GRIDLINEWIDTH, GRIDLINEMODE);
max = bounds.origin.x + bounds.size.width;
for(x = bounds.origin.x; x < max; x += gridSize)
PScompositerect(x, bounds.origin.y, GRIDLINEWIDTH, bounds.size.height, GRIDLINEMODE);
return self;
}
- updateBitmap:(NXPoint *) point
{
NXRect rect;
mutex_lock(lock); {
[invisibleView getFrame:&rect];
#ifdef DEBUG
fprintf(stderr, "NXReadBitmap(rect:{%f,%f}, wide:%d, high:%d, bps:%d, spp:%d)\n",
rect.size.width, rect.size.height, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel);
#endif
[invisibleWindow moveTo:point->x - offset.width :point->y - offset.height];
[invisibleWindow orderFront:self]; {
(void) [invisibleView lockFocus]; {
NXReadBitmap(&rect, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel, planarConfig, photoInt, data[0], data[1], data[2], data[3], data[4]);
} [invisibleView unlockFocus];
} [invisibleWindow orderOut:self];
} mutex_unlock(lock);
bitsPerPixel = bitsPerSample * ((planarConfig == NX_PLANAR) ? 1 : samplesPerPixel);
bytesPerRow = (7 + pixelsWide * bitsPerSample * ((planarConfig == NX_PLANAR) ? 1 : samplesPerPixel)) / 8;
colorSpace = ((photoInt & NX_CMYKMASK) == NX_CMYKMASK) ? NX_CMYKColorSpace : (photoInt & NX_CMYKMASK);
return self;
}
- (int) flags { return flags; }
- (NXPoint *) mouse { return &mouse; }
- (float) scale { return scale; }
- setScale:(float) value
{
mutex_lock(lock); {
scale = value;
} mutex_unlock(lock);
return self;
}
- (float) gridSize { return gridSize; }
- setGridSize:(float) value
{
mutex_lock(lock); {
gridSize = value;
} mutex_unlock(lock);
return self;
}
- (BOOL) isFrozen { return frozen; }
- setFrozen:(BOOL) state
{
mutex_lock(lock); {
if (frozen = state) (void) [window removeFromEventMask:NX_MOUSEMOVEDMASK];
else (void) [window addToEventMask:NX_MOUSEMOVEDMASK];
} mutex_unlock(lock);
return self;
}
- setShowGrid:(BOOL) state
{
mutex_lock(lock); {
showGrid = state;
} mutex_unlock(lock);
return [self display];
}
- setShowCursor:(BOOL) state
{
mutex_lock(lock); {
showCursor = state;
} mutex_unlock(lock);
return [self display];
}
- createWindows
{
NXRect rect;
size_t size;
unsigned int i;
mutex_lock(lock); {
rect = bounds;
offset.width = (rect.size.width = sizeof(int) * ceil((bounds.size.width / scale) / sizeof(int))) * HALF;
offset.height = (rect.size.height = ceil(bounds.size.height / scale)) * HALF;
if (invisibleWindow != nil) [invisibleWindow sizeWindow:rect.size.width :rect.size.height];
else {
invisibleWindow = [[Window alloc] initContent:&rect style:NX_PLAINSTYLE backing:NX_NONRETAINED buttonMask:NX_NOBUTTONS defer:NO];
PSsetautofill(NO, [invisibleWindow windowNum]);
NXSetWindowLevel([invisibleWindow windowNum], MAGNIFYLEVEL);
[invisibleWindow setEventMask:NX_NULLEVENTMASK];
[(invisibleView = [invisibleWindow contentView]) allocateGState];
}
[invisibleView getFrame:&rect];
virtualBounds = rect;
virtualBounds.size.width *= scale;
virtualBounds.size.height *= scale;
(void) [invisibleView lockFocus]; {
NXSizeBitmap(&rect, (int *) &size, &pixelsWide, &pixelsHigh, &bitsPerSample, &samplesPerPixel, &planarConfig, &photoInt);
} [invisibleView unlockFocus];
#ifdef DEBUG
fprintf(stderr, "NXSizeBitmap(rect:{%f,%f}, wide:%d, high:%d, bps:%d, spp:%d)\n",
rect.size.width, rect.size.height, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel);
#endif
for(i = 0; i < NX_MAXPLANES; i++) {
if(data[i] == NULL) data[i] = malloc(size);
else if (size > malloc_size(data[i])) data[i] = realloc(data[i], size);
if(planarConfig == NX_MESHED) break;
}
} mutex_unlock(lock);
return [[self updateBitmap:&mouse] display];
}
void timer(DPSTimedEntry teNumber, double now, id self)
{
if (![self isFrozen]) {
NXPoint *mouse = [self mouse];
Window *window = [self window];
[window getMouseLocation:mouse];
[window convertBaseToScreen:mouse];
[[self updateBitmap:mouse] display];
}
}
@end